package com.cjj.common.utils;

import cn.hutool.core.date.CalendarUtil;
import com.cjj.common.framework.exception.BusinessException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import javax.validation.constraints.NotNull;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.util.*;

/**
 * @author DoyuTu
 * @version 1.0.0
 * @date 2019/8/16 17:45
 * @description
 */
public class DateUtil {

    private static final ZoneOffset DEFAULT_ZONE_OFFSET = ZoneOffset.of("+8");

    private static ZoneId DEFAULT_ZONE_ID = ZoneId.of("+8");

    public static Long date2Second(Date date) {
        if (date == null) {
            return null;
        }
        return date.toInstant().getEpochSecond();
    }

    public static int date2SecondInt(Date date) {
        if (date == null) {
            return 0;
        }
        return ((int)date.toInstant().getEpochSecond());
    }

    public static Date second2Date(Integer second) {
        if (second == null) {
            return null;
        }
        return new Date(second * 1000L);
    }

    public static Date second2Date(Long second) {
        if (second == null) {
            return null;
        }
        return new Date(second * 1000L);
    }

    public static Date zeroSecond2Date(Integer second) {
        if (second == null || second == 0) {
            return null;
        }
        return new Date(second * 1000L);
    }

    public static Date zeroSecond2Date(Long second) {
        if (second == null || second == 0) {
            return null;
        }
        return new Date(second * 1000L);
    }

    public static int currentSecond() {
        return ((int) Instant.now().getEpochSecond());
    }

    public static Date getTodayStartDate() {
        return DateUtils.truncate(new Date(), Calendar.DAY_OF_MONTH);
    }

    public static long getTodayStartSecond() {
        return DateUtil.date2Second(getTodayStartDate());
    }

    public static long getTodayStartSecond(@NotNull Date date) {
        return DateUtil.date2Second(DateUtils.truncate(date, Calendar.DAY_OF_MONTH));
    }

    public static Date getTodayEndDate() {
        return DateUtils.ceiling(new Date(), Calendar.DAY_OF_MONTH);
    }

    public static long getTodayEndSecond() {
        return DateUtil.date2Second(getTodayEndDate());
    }

    public static long getTodayEndSecond(@NotNull Date date) {
        return DateUtil.date2Second(DateUtils.ceiling(date, Calendar.DAY_OF_MONTH));
    }

    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(DEFAULT_ZONE_ID).toInstant());
    }

    /**
     * 获取n天后的时间
     *
     * @param days
     * @return
     */
    public static LocalDate getAfterDate(Integer days, LocalDate date) {
        if (days == null) {
            return LocalDate.now();
        }
        return date.plusDays(days);
    }

    /**
     * 获取n天后的时间
     *
     * @param days
     * @return
     */
    public static Date getAfterDate(Integer days, Date date) {
        LocalDate localDate = dateToLocalDate(date);
        LocalDate afterLocalDate = getAfterDate(days, localDate);
        return localDateToDate(afterLocalDate);
    }

    /**
     * 获取n天前的时间
     *
     * @param days
     * @return
     */
    public static LocalDate getBeforeDate(Integer days, LocalDate date) {
        if (days == null) {
            return LocalDate.now();
        }
        return date.minusDays(days);
    }

    /**
     * 获取n天前的时间
     *
     * @param days
     * @return
     */
    public static Date getBeforeDate(Integer days, Date date) {
        LocalDate localDate = dateToLocalDate(date);
        LocalDate afterLocalDate = getBeforeDate(days, localDate);
        return localDateToDate(afterLocalDate);
    }

    public static LocalDate dateToLocalDate(Date date) {
        ZoneId zoneId = ZoneId.systemDefault();
        if (date == null) {
            return null;
        }
        return date.toInstant().atZone(zoneId).toLocalDate();
    }

    public static Date localDateToDate(LocalDate localDate) {
        if (localDate == null) {
            return new Date();
        }
        return Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
    }

    public static String timestampToString(Object timestamp) {
        return dateToString(timestampToDate(timestamp));
    }

    public static String dateToString(Date date) {
        if (date != null) {
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
            return simpleDateFormat.format(date);
        }
        return null;
    }

    public static String parseSecondToStr(long second) {
        if (second == 0) {
            return "";
        }
        return parseSecondFormat(second, "yyyy-MM-dd HH:mm:ss");
    }

    public static String parseSecondFormat(long second, String format) {
        return DateFormatUtils.format(new Date(second * 1000), format);
    }

//    获取所传日期起始时间 10:00→0:00
//    public static Date getTheDayStart(Date date){
//        if(date==null){
//            return null;
//        }
//    }

    private static final String[] PATTERN = {"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy/MM/dd", "yyyy/MM/dd HH:mm", "yyyy/MM/dd HH:mm:ss", "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"};

    public static Date formatStr2Date(String date) {
        if (StringUtils.isBlank(date)) {
            return null;
        }
        try {
            return DateUtils.parseDate(date, PATTERN);
        } catch (ParseException e) {
            throw new BusinessException("日期格式错误");
        }
    }

    // 获取所传日期结束时间 10:00：59→23:59:59
    public static Date getTheDayEnd(Date date) {
        if (date == null) {
            return null;
        }
        return formatStr2Date(DateFormatUtils.format(date, "yyyy-MM-dd 23:59:59"));
    }

    /**
     * 十位时间戳转为时间
     *
     * @Author:huxin
     * @Parame:[timestamp]
     * @Return:java.util.Date
     */
    public static Date timestampToDate(Object timestamp) {
        if (timestamp instanceof Integer) {
            if (timestamp.equals(0)) {
                return null;
            }
            int time = (int) timestamp;
            Long longTime = (long) time * 1000;
            return new Date(longTime);
        } else if (timestamp instanceof Long) {
            if (timestamp.equals(0L)) {
                return null;
            }else if ((timestamp + "").length() == 10) {
                return new Date((long) timestamp * 1000);
            }else {
                return new Date((long)timestamp);
            }
        } else {
            return null;
        }
    }

    public static Date beginOfDay(int offset){
        Calendar calendar = CalendarUtil.beginOfDay(new GregorianCalendar(TimeZone.getTimeZone("GMT+8")));
        calendar.add(Calendar.DAY_OF_WEEK,offset);
        return calendar.getTime();
    }

    public static Date beginOfDay(){
        return beginOfDay(0);
    }

    public static Date endOfDay(int offset){
        Calendar calendar = CalendarUtil.endOfDay(new GregorianCalendar(TimeZone.getTimeZone("GMT+8")));
        calendar.add(Calendar.DAY_OF_WEEK,offset);
        return calendar.getTime();
    }

    public static Date endOfDay(){
        return endOfDay(0);
    }

    public static Date beginOfWeek(int offset){
        Calendar calendar = CalendarUtil.beginOfWeek(new GregorianCalendar(TimeZone.getTimeZone("GMT+8")));
        calendar.add(Calendar.WEEK_OF_MONTH,offset);
        return calendar.getTime();
    }

    public static Date beginOfWeek(){
        return beginOfWeek(0);
    }

    public static Date endOfWeek(int offset){
        Calendar calendar = CalendarUtil.endOfWeek(new GregorianCalendar(TimeZone.getTimeZone("GMT+8")));
        calendar.add(Calendar.WEEK_OF_MONTH,offset);
        return calendar.getTime();
    }

    public static Date endOfWeek(){
        return endOfWeek(0);
    }

    /**
     * 是否闰年
     *
     * @param year 年
     * @return 是否闰年
     */
    public static boolean isLeapYear(int year) {
        return new GregorianCalendar().isLeapYear(year);
    }

    /**
     * 获取近n天日期
     * @return 近n天日期
     */
    public static List<String> getDaysNearDay(Integer n){
        SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd" );
        Date today = new Date();
        List<String> list = new ArrayList<>();
        for (int i = 1; i <= n; i++) {
            Calendar theCa = Calendar.getInstance();
            theCa.setTime(today);
            theCa.add(Calendar.DATE, -i);
            Date start = theCa.getTime();
            String startDate = sdf.format(start);
            list.add(startDate);
        }
        return list;
    }

    /**
     * 获取1年月份
     * @return 近1年月份
     */
    public static List<String> getInitMonthMapWithZero(){
        List<String> list = new ArrayList<>();
        Calendar c = Calendar.getInstance();
        for(int i = 0; i < 12; i ++){
            int k = c.get(Calendar.YEAR);
            int j = c.get(Calendar.MONTH) + 1 - i;
            String date = "";
            if(j >= 1){
                date = k + "-" + (j >= 10 ? "" : "0") + j;
            } else {
                int p = 11 - i;
                int m = c.get(Calendar.YEAR) - 1;
                int n = c.get(Calendar.MONTH) + 2 + p;
                date = m + "-" + (n >= 10 ? "" : "0") + n;
            }
            list.add(date);
        }
        return list;
    }

    public static void main(String[] args) {
        int x = 1;
        System.out.println((x + "").length());
    }
}
